#include <fcntl.h>
#include <unistd.h>
#include <curses.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <time.h>
#define SERVPORT 3333 /*服务器监听端口号 */
#define BACKLOG 10 /* 最大同时连接请求数 */
#define MAXDATASIZE 4096 /*每次最大数据传输量 */
#define DIS_COLS 8 /*需要提取的列号*/
#define COL_MAX 12 /*DrawScr中最大显示的进程数*/
#define PRO_NUM 10 /*需在客户端提取的进程数*/

typedef struct
{
	char hostname[200];
	long updatetm;
	int pid[500];
	float cpu[500];
	float mem[500];
	float max,min,ave;
}COMPUTER;

COMPUTER host[10];
int num=0;

/*f3.h---begin*/
int kbhit()	/*判断有否输入*/
{
	int n;
	ioctl(0,FIONREAD,&n);
	return n;
}
int str2float(char ch[],float * final)	/*自串转化浮点*/
{
	
	int i;
	for(i=0;ch[i];i++)
	{
		if(!((ch[i]>='0'&&ch[i]<='9')||ch[i]=='.'))
			return 0;
	}
	sscanf(ch,"%f",final);
	return 1;
}

int str2li(char in[],long *dst)
{
	int i;
	for(i=0;in[i];i++)
	{
		if(!((in[i]>='0'&&in[i]<='9')||in[i]=='.'))
		{
			in[i]=0;
			break;
		}
	}
	sscanf(in,"%ld",dst);
	return 1;
}
int GetMMA(float in[],float *max,float *min,float *ave)	/*获取最大,最小,均值*/
{
	*min = *max = in[0];
	*ave = 0;
	int i=1;
	for(i=0;in[i]>=0;i++)
	{
		*ave += in[i];
		if(in[i] < *min)
			*min=in[i];
		else if(in[i] > *max)
			*max=in[i];
	}
	*ave /= i;
	return 1;
}

int GetCOLk(char in[],int k,char dst[])	/*获取in串中的第K个字段,存入dst*/
{
	int i=0,j=1,p;
	char c,c1;
	while(in[i])
	{
		c1=in[i++];
		c=in[i];
		c!=' ' && c1==' ' && j++;
		if(j==k && c1!=' ')
		{
			for(p=0;dst[p]!='\0';p++);
			dst[p]=c1;
			dst[p+1]='\0';
		}
	}
	return 1;
}

int file2float(FILE *fp,float cpu[],int pid[])	/*从流中取得CPU和PID*/
{
	int j,l=0;
	char c,ch[20],cpid[20],buf[1024];
//	FILE *fp;
//	fp = popen(cmd,"r");
	c=getc(fp);
	do{
		j=0;
		strcpy(ch,"");
		strcpy(cpid,"");
		while(c!='\n'&&j<1023)
		{
			buf[j]=c;
			j++;
			c=getc(fp);
		}
		buf[j]='\0';
		GetCOLk(buf,3,ch);
		GetCOLk(buf,2,cpid);
//		puts(cpid);
		if(c!=EOF&&str2float(ch,&cpu[l]))
		{
			pid[l]=atoi(cpid);
			l++;
		}
		c=getc(fp);
	}while(c!=EOF);
	cpu[l]=-1;
	pid[l]=-1;
//	pclose(fp);
	return 0;
}


int str2computer(char in[],float cpu[],int pid[])	/*从流中取得CPU和PID*/
{
	int j=0,l=0;
	char ch[20],cpid[20],buf[1024],*p=in;
	do{
		j=0;
		strcpy(ch,"");
		strcpy(cpid,"");
		while(*p!='\n')
		{
			buf[j]=*p;
			j++;
			p++;
		}
		buf[j]='\0';
		GetCOLk(buf,3,ch);
		GetCOLk(buf,2,cpid);
//		puts(cpid);
		if(str2float(ch,&cpu[l]))
		{
			pid[l]=atoi(cpid);
			l++;
		}
		p++;
	}while(*p!=0);
	cpu[l]=-1;
	pid[l]=-1;
//	pclose(fp);
	return 0;
}

int intlen(int in)	/*反回in的长度*/
{
	int i=0;
	while(in)
	{
		i++;
		in/=10;
	}
	return i;
}

int li2str(long in,char str[])
{
	int i=0,len;
	char tmp[50];
	while(in)
	{
		tmp[i]=in%10+'0';
		in/=10;
		i++;
	}
	tmp[i]=0;
	len=strlen(tmp);
	for(i=0;i<len;i++)
	{
		str[len-1-i]=tmp[i];
	}
	str[len]=0;
	return 1;
}

int cuthh(char in[])
{
	int i;
	for(i=0;in[i];i++)
	{
		if(in[i]=='\n')
		{
			in[i]=0;
			break;
		}
	}
	return 1;
}

int getinfo(char info[],char cmd[])
{
	char c;
	int i;
	FILE *fp;
	fp=popen(cmd,"r");
	c=getc(fp);
	for(i=0;c!=EOF;i++)
	{
		info[i]=c;
		c=getc(fp);
	}
	info[i]=0;
	pclose(fp);
	return 1;
}
/*f3.h---end*/
/*server.h---begin*/
int float2graph(float in,int x,int y,int my) /*横式*/
{
	in>0.1 && mvaddstr(x,y++,"|");
	float max = COL_MAX;
	int len=(in/max)*(my-y-3),i;
	for(i=0;i<len;i++)
	{
		mvprintw(x,y+i,"|");
	}
	mvaddstr(x,y+i," ");
	mvprintw(x,y+i+1,"%.1f",in);
	return 0;	
}
int float2graph2(float in,int x,int y,float maxin) /*竖式*/
{
	mvaddch(x--,y,ACS_HLINE);
	float max = maxin+5;
	int high = (in/max)*(x-3),i;
	for(i=0;i<high;i++)
	{
		mvaddch(x-i,y,ACS_HLINE);

	}
	mvprintw(x-i,y,"%.1f",in);
	return 0;
}
int InitCOMPUTER(char info[],COMPUTER *in)	/*初始,从文件读入Structure*/
{

	memset(in->cpu,-1,500);
	memset(in->pid,-1,500);
	str2computer(info,in->cpu,in->pid);
	GetMMA(in->cpu,&(in->max),&(in->min),&(in->ave));
	return 0;
}
int DrawScr(COMPUTER *in)	/*Stucture输出*/
{
	clear();
	int mx,my,x,y,i,col_len;
	char tmstr[50];
	strcpy(tmstr,ctime(&(in->updatetm)));
	cuthh(tmstr);
	getmaxyx(stdscr,mx,my);
	col_len = (my-6)/COL_MAX;
	x = mx-4;
	y = 3;
	box(stdscr, ACS_VLINE, ACS_HLINE); /*draw a box*/
	for(i=y;i<my-3;i++)
		mvaddch(x,i,ACS_HLINE);
	for(i=0;i<COL_MAX&&in->cpu[i]>1e-6;i++)
	{
		mvprintw(x+1,y+col_len*i,"%5d",in->pid[i]);
		float2graph2(in->cpu[i],x-1,y+col_len*i+2,in->cpu[0]);
	}
	
	attron(A_REVERSE);
	mvprintw(1,my-10-strlen(in->hostname),"Computer:%s",in->hostname);
	mvprintw(2,my-13-strlen(tmstr),"Update time:%s",tmstr);
	mvaddstr(mx-2,3,"Press anykey to Quit...");
	mvprintw(mx-2,my-30,"Max:%4.1f  Min:%4.1f  Ave:%4.1f",in->max,in->min,in->ave);
	attroff(A_REVERSE);
	refresh();
	return 1;
}

void *sub_thread(void *arg)
{
    int *p = (int*)arg,client_fd;
    client_fd = *p;
    int recvbytes=1,host_id;
    host_id=num;
    num++;
    printf("%d\n",*p);
    char buf[4096],tmp[4096];
    while(1)
    {
		recvbytes=recv(client_fd, buf, MAXDATASIZE, 0);
		if(strcmp(buf,"end")==0||recvbytes<1)break;
		strcpy(tmp,strtok(buf,"|||"));
		InitCOMPUTER(tmp,host+host_id);
		strcpy(tmp,strtok(NULL,"|||"));
		strcpy(host[host_id].hostname,tmp);
		strcpy(tmp,strtok(NULL,"|||"));
		str2li(tmp,&host[host_id].updatetm);
		strcpy(buf,"");
    }
	close(client_fd);
	return NULL;
}

void *server_main(void *arg)
{
        int sockfd,client_fd; /*sock_fd：监听socket；client_fd：数据传输socket */
        pthread_t th;
        struct sockaddr_in my_addr; /* 本机地址信息 */
        struct sockaddr_in remote_addr; /* 客户端地址信息 */
        socklen_t sin_size;
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        {
                perror("socket创建出错！"); exit(1);
        }
        my_addr.sin_family=AF_INET;
        my_addr.sin_port=htons(SERVPORT);
        my_addr.sin_addr.s_addr = INADDR_ANY;
        bzero(&(my_addr.sin_zero),8);
        if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
        {
                perror("bind出错！");
                exit(1);
        }
        if (listen(sockfd, BACKLOG) == -1)
        {
                perror("listen出错！");
                exit(1);
        }
        while(1)
        {
                sin_size = sizeof(struct sockaddr_in);
                if ((client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_size)) == -1)
                {
                        perror("accept出错");
                        continue;
                }
                //printf("received a connection from %s\n", inet_ntoa(remote_addr.sin_addr));
                pthread_create(&th,NULL,sub_thread,&client_fd);/*创建子线程用于接受数据*/
        }
	return NULL;
}
int server()
{
    int bo;
    pthread_t th;
    bo = pthread_create(&th,NULL,server_main,NULL);
    if(bo==0)
        return 1;
    return 0;
}
/*server.h---end*/

void *main_thread1(void *arc)
{
	int i;
	while(1)
	{
		clear();
		printw("Cliented Hosts:%d\n",num);
		for(i=0;i<num;i++)
		{
			printw("Hosts%d:%s\t",i+1,host[i].hostname);
			printw("Last update:%d\n",host[i].updatetm);
		}
		refresh();
		sleep(1);
	}
}
void *main_draw(void *arc)
{
	int sel=*((int *)arc);
	while(1)
	{
		DrawScr(host+sel-1);
		sleep(1);
	}
}
int main()
{
	int sel;
	pthread_t th;
	if(!server())
	{
		puts("Init Fail!!");
		exit(0);
	}
		
	initscr();
	while(1)
	{
		pthread_create(&th,NULL,main_thread1,NULL);
		sel=getch();
		while(sel>255)sel=getch();
		pthread_cancel(th);
		sel-='0';
		if(sel<0||sel>9)break;
		pthread_create(&th,NULL,main_draw,&sel);
		sel=getch();
		while(sel>255)sel=getch();
		pthread_cancel(th);
	}
	
	endwin();
//	kill(0,15);
	return 0;
}
